#pragma once
#include "../ComPropVariant.h"
#include "../RefCountedObject.h"
#include "SevenZipLibrary.h"

namespace SevenZip
{

struct CSevenZipMethod
{
	enum Properties
	{
		PROPID_ID,
		PROPID_Name,
		PROPID_Decoder,
		PROPID_Encoder,
		PROPID_InStreams,
		PROPID_OutStreams,
		PROPID_Description,
		PROPID_DecoderIsAssigned,
		PROPID_EncoderIsAssigned
	};

	CStringW Name;
	CLSID    EncoderClassID;
	CLSID    DecoderClassID;

	STDMETHODIMP Initialize(CSevenZipLibraryPtr &, UINT32);
};

struct CSevenZipFormat
{
	enum Properties
	{
		PROPID_Name = 0,
		PROPID_ClassID = 1,
		PROPID_Extension = 2,
		PROPID_AddExtension = 3,
		PROPID_Update = 4,
		PROPID_KeepName = 5,
		PROPID_StartSignature = 6,
		PROPID_FinishSignature = 7,
		PROPID_Associate = 8,
	};

	template<typename T>
	STDMETHODIMP CreateInstance(CComPtrBase<T> &) CONST;
	STDMETHODIMP MatchesExtension(__in LPCWSTR) CONST;

	STDMETHODIMP Initialize(CSevenZipLibraryPtr &, UINT32);

private:

	CStringW            _Name;
	CLSID               _ClassID;
	CSevenZipLibraryPtr _Library;
	CAtlArray<CStringW> _Extensions;
};

struct CSevenZipFactory : CRefCountedObject<CSevenZipFactory>
{
	STDMETHODIMP AddLibrary(__in LPCWSTR);
	STDMETHODIMP AddLibrary(CSevenZipLibraryPtr &);

	STDMETHODIMP FindFormatByExtension(__in LPCWSTR, __out CAtlArray<const CSevenZipFormat*> &) CONST;

private:

	STDMETHODIMP AddMethods(CSevenZipLibraryPtr &);
	STDMETHODIMP AddFormats(CSevenZipLibraryPtr &);

	CAtlArray<CSevenZipMethod>  _Methods;
	CAtlArray<CSevenZipFormat>  _Formats;
};

typedef CComPtr<CSevenZipFactory> CSevenZipFactoryPtr;

}

template<typename T>
STDMETHODIMP SevenZip::CSevenZipFormat::CreateInstance(CComPtrBase<T> & Result) CONST
{
	return _Library->CreateObject<T>(_ClassID, Result);
}
